package com.bitBusy.manageyourriches.activity;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ExpandableListView;
import android.widget.TextView;

import com.bitBusy.manageyourriches.R;
import com.bitBusy.manageyourriches.database.contactClasses.SpendingCategory;
import com.bitBusy.manageyourriches.database.managers.DatabaseInteractor;
import com.bitBusy.manageyourriches.database.managers.DateTimeManager;
import com.bitBusy.manageyourriches.utilityClasses.adapters.CategoriesExpandableListAdapter;
import com.bitBusy.manageyourriches.utilityClasses.navigation.ActionBarChoice;
import com.bitBusy.manageyourriches.utilityClasses.pickers.DateChangeListener;

public class ViewExpensesActivity extends FragmentActivity implements DateChangeListener{
	
	/** Key for category chosen, in the intent object used to start the next activity */
    public final static String CATEGORY_CHOSEN = "com.bitBusy.manageMyRiches.CATEGORYCHOSEN";
    
    /** Key for SUBcategory chosen, in the intent object used to start the next activity */
    public final static String SUBCATEGORY_CHOSEN = "com.bitBusy.manageMyRiches.SUBCATEGORYCHOSEN";

    /** Key for amt chosen, in the intent object used to start the next activity */
    public final static String AMOUNT_CHOSEN = "com.bitBusy.manageMyRiches.AMOUNTCHOSEN";
    
    /** Key for payment meth chosen, in the intent object used to start the next activity */
    public final static String PAYMENTMETHOD_CHOSEN = "com.bitBusy.manageMyRiches.PAYMENTMETHODCHOSEN";

    /** Key for note chosen, in the intent object used to start the next activity */
    public final static String NOTE_CHOSEN = "com.bitBusy.manageMyRiches.NOTECHOSEN";
    
    /** Key for date chosen, in the intent object used to start the next activity */
    public final static String DATE_CHOSEN = "com.bitBusy.manageMyRiches.DATECHOSEN";

    /** Key for time chosen, in the intent object used to start the next activity */
    public final static String TIME_CHOSEN = "com.bitBusy.manageMyRiches.TIMECHOSEN";
   
    /** categories sorted*/
    private static final String CATEGORIESASCENDING = "categories (a-z)";
    
    private static final String CATEGORIESDESCENDING = "categories (z-a)";
    /** amount*/
    private static final String AMOUNT = "amount";
    
    /** amount sorted*/
    private static final String AMOUNTASCENDING = " amount \n (low-high)";
    
    private static final String AMOUNTDESCENDING = " amount \n (high-low)";

    /**categories*/
    private static final String CATEGORIES = "categories";
    
   /**how is it sorted*/
   private boolean isCategorySorted = true;
   
   /**category ascending*/
   private boolean isCategoryAscending = true;
   
   /** amount ascending*/
   private boolean isAmountAscending = false;
  
   
   /** map of spending category and amount */
   private Map<SpendingCategory, Double> myCategoryAmountMap;
   

	/**From date*/
	private int myFromDate;
	
	/**To date*/
	private int myToDate;
	
	 /**Database interactor object for this activity*/
		private DatabaseInteractor myDBInteractor;
		
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_view_expenses);
		myCategoryAmountMap = null;
		myDBInteractor = new DatabaseInteractor(this);		
		setDateButtons();
		setTotalSum();
		populateMap();
		setExpandableLists(isCategorySorted);

	}
	
	/** method to get the data population fired*/
	public void updateData(SpendingCategory the_categoryName, CategoriesExpandableListAdapter the_caller)
	{
		if (the_categoryName != null && myCategoryAmountMap != null)
		{
			double amount = myDBInteractor.getTotalSpentCategory(the_categoryName.getName(), myFromDate, myToDate);
			myCategoryAmountMap.put(the_categoryName, amount);
			the_caller.updateMapAmount(the_categoryName, amount);
			
			
		}
	}
	
	/**Method to set date buttons*/
	private void setDateButtons()
	{
		String today = DateTimeManager.getCurrentDate();
		
		Button toDateButton = (Button) findViewById(R.id.viewExpenses_toDateButton);
		myToDate = DateTimeManager.parseForDBDate(today);
		toDateButton.setText(today);
		
		Button fromDateButton = (Button) findViewById(R.id.viewExpenses_fromDateButton);
		fromDateButton.setText(new StringBuilder().append(String.valueOf(DateTimeManager.getPreviousMonth())).append
				(today.substring(today.indexOf(DateTimeManager.DATESPLITTER))));
		myFromDate = DateTimeManager.parseForDBDate(fromDateButton.getText().toString());

		
	}
	
	/**Method to set total amount spent between the from and to dates
	 */
	public void setTotalSum() 
	{
		TextView totalSum = (TextView) findViewById(R.id.viewExpenses_totalSpentAmt);
		totalSum.setText(String.valueOf(myDBInteractor.getTotalSpent(myFromDate, myToDate)));
	}

	
	/** Method to set expandable lists on display
	 * @param boolean to indicate if sorted by categories(true)*/
	private void setExpandableLists(boolean the_isSortedByCategory)
	{
		ExpandableListView list = (ExpandableListView) findViewById(R.id.viewExpenses_categoryAmtList);
		CategoriesExpandableListAdapter listAdapter = null;
		if (the_isSortedByCategory)
		{
			listAdapter = new CategoriesExpandableListAdapter(this, list, getSortedByCategoryMap(), myFromDate,
				 							myToDate);
		}
		else
		{
			listAdapter = new CategoriesExpandableListAdapter(this, list, getSortedByAmountMap(), myFromDate,
						myToDate);

		}
		  list.setAdapter(listAdapter);	  
	}

	/**Method to change from date
	 * @param the view object
	 */
	public void changeFromDate(View the_view)
	{
		DateTimeManager.changeDate(this, this, (Button) findViewById(R.id.viewExpenses_fromDateButton));		
	}
	
	/**Method to change to date
	 * @param the view object
	 */
	public void changeToDate(View the_view)
	{
		DateTimeManager.changeDate(this, this, (Button) findViewById(R.id.viewExpenses_toDateButton));
	}
	

	/* (non-Javadoc)
	 * @see com.bitBusy.manageyourriches.utilityClasses.pickers.DateChangeListener#dateHasChanged(android.widget.TextView)
	 */
	@Override
	public void dateHasChanged(TextView the_view) {
		if (the_view != null)
		{
			if (the_view.getId() == R.id.viewExpenses_fromDateButton)
			{
				myFromDate = DateTimeManager.parseForDBDate(the_view.getText().toString());
			}
			else if (the_view.getId() == R.id.viewExpenses_toDateButton)
			{
				myToDate = DateTimeManager.parseForDBDate(the_view.getText().toString());
			}
			setTotalSum();
			populateMap();
			setExpandableLists(isCategorySorted);

			}
		
	}
	
	/** sort ilst by categories(keys)
	 * @param list 
	 * @return sorted list
	 */
	public void sortCategories(View the_view)
	{
			isCategorySorted = true;
			isCategoryAscending = !isCategoryAscending;
			setExpandableLists(isCategorySorted);
		

	}
	
	/** sort list by amount
	 * @param list 
	 * @return sorted list
	 */
	public void sortAmount(View the_view)
	{
			isCategorySorted = false;
			isAmountAscending = !isAmountAscending;
			setExpandableLists(isCategorySorted);
	}
	
	/** sets value of sort buttons on screen
	 * @param for category button
	 * @param for amount button
	 */
	private void setSortButtons(String the_categoryText, String the_amountText)
	{
		Button category = (Button)findViewById(R.id.viewExpenses_categoriesButton);
		Button amount = (Button)findViewById(R.id.viewExpenses_amountButton);
		category.setText(the_categoryText);
		amount.setText(the_amountText);

		
	}
	
	/** gets sorted map based on categories (key)
	 * @return map
	 */
	private Map<SpendingCategory, Double> getSortedByCategoryMap()
	{
		TreeMap<SpendingCategory, Double> sortedMap = (myCategoryAmountMap == null)?null:new TreeMap<SpendingCategory, Double>(myCategoryAmountMap);
		if (isCategoryAscending)
		{
			setSortButtons(CATEGORIESASCENDING, AMOUNT);
			return sortedMap;
		}
		else
		{
			setSortButtons(CATEGORIESDESCENDING, AMOUNT);
			return sortedMap.descendingMap();
		}
	}

	/** gets sorted by amount map
	 * @return sorted map
	 */

	private Map<SpendingCategory, Double> getSortedByAmountMap()
	{
		if (isAmountAscending)
		{
			setSortButtons(CATEGORIES, AMOUNTASCENDING);
			return getAscendingAmountMap();

		}
		else
		{
			setSortButtons(CATEGORIES, AMOUNTDESCENDING);
			return getDescendingAmountMap();
		}	

	}
	
	/** method to get map in ascending order of amount
	 * @return map
	 */
	private Map<SpendingCategory, Double> getAscendingAmountMap()
	{
		Map<SpendingCategory, Double> sortedMap = null;
		List<Map.Entry<SpendingCategory, Double>>list = (myCategoryAmountMap == null)?null:
										new LinkedList<Map.Entry<SpendingCategory, Double>>(myCategoryAmountMap.entrySet());
		 
		if (list != null)
		{
			// sort list based on comparator
			Collections.sort(list, new Comparator<Map.Entry<SpendingCategory, Double>>() {
				@Override
				public int compare(Entry<SpendingCategory, Double> first,
						Entry<SpendingCategory, Double> second) {
					return first.getValue().compareTo(second.getValue());
				}

				
			});
	 
			    sortedMap = new LinkedHashMap<SpendingCategory, Double>();
				for (Iterator<Entry<SpendingCategory, Double>> list_iterator = list.iterator(); list_iterator.hasNext();) {
					Map.Entry<SpendingCategory, Double> entry =	(Map.Entry<SpendingCategory, Double>) list_iterator.next();
					SpendingCategory category = entry.getKey();
					Double amount = entry.getValue();
					sortedMap.put(category, amount);
			}
		}
		return sortedMap;
	
	}
	
	/** method to get descending amount order map
	 * @return map
	 */
	private Map<SpendingCategory, Double> getDescendingAmountMap()
	{
		Map<SpendingCategory, Double> sortedMap = null;
		List<Map.Entry<SpendingCategory, Double>>list = (myCategoryAmountMap == null)?null:
										new LinkedList<Map.Entry<SpendingCategory, Double>>(myCategoryAmountMap.entrySet());
		 
		if (list != null)
		{
			// sort list based on comparator
			Collections.sort(list, new Comparator<Map.Entry<SpendingCategory, Double>>() {
				@Override
				public int compare(Entry<SpendingCategory, Double> first,
						Entry<SpendingCategory, Double> second) {
					return second.getValue().compareTo(first.getValue());
				}

				
			});
	 
			    sortedMap = new LinkedHashMap<SpendingCategory, Double>();
				for (Iterator<Entry<SpendingCategory, Double>> list_iterator = list.iterator(); list_iterator.hasNext();) {
					Map.Entry<SpendingCategory, Double> entry =	(Map.Entry<SpendingCategory, Double>) list_iterator.next();
					SpendingCategory category = entry.getKey();
					Double amount = entry.getValue();
					sortedMap.put(category, amount);
			}
		}
		return sortedMap;
	
	}
	/** populate map */
	private void populateMap()
	{
		myCategoryAmountMap = new HashMap<SpendingCategory, Double>();
		List<SpendingCategory> categories = myDBInteractor.getAllSpendingCategories();
		double amount;
		for (SpendingCategory category: categories)
		{
			amount = myDBInteractor.getTotalSpentCategory(category.getName(), myFromDate, myToDate);
			myCategoryAmountMap.put(category, amount);

		}
	}
	
	 @Override
	  public boolean onCreateOptionsMenu(Menu the_menu) {
	    MenuInflater inflater = getMenuInflater();
	    inflater.inflate(R.menu.actionbar_menu, the_menu);
	    return true;
	  }
	 @Override
	  public boolean onOptionsItemSelected(MenuItem the_item) {
	    ActionBarChoice.choiceMade(this, the_item.getItemId());

	    return true;
	  }
	
	
	
	
}